#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
备份设置对话框
提供备份配置管理和备份文件列表查看功能
"""

import sys
import os
import logging
from pathlib import Path
from datetime import datetime
from typing import Optional, List, Dict

from PyQt6.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, QGroupBox,
    QCheckBox, QSpinBox, QComboBox, QLineEdit, QPushButton,
    QTableWidget, QTableWidgetItem, QLabel, QMessageBox,
    QFileDialog, QHeaderView, QTabWidget, QWidget, QTextEdit,
    QProgressBar, QSplitter
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt6.QtGui import QFont, QIcon

try:
    from ..utils.logger_manager import get_system_logger, OperationType, LogLevel
except ImportError:
    try:
        from src.utils.logger_manager import get_system_logger, OperationType, LogLevel
    except ImportError:
        get_system_logger = None
        OperationType = None
        LogLevel = None

logger = logging.getLogger(__name__)

class BackupConfigWidget(QWidget):
    """备份配置组件"""
    
    def __init__(self, backup_manager, parent=None):
        super().__init__(parent)
        self.backup_manager = backup_manager
        
        # 系统日志管理器
        self.system_logger = get_system_logger() if get_system_logger else None
        
        self.init_ui()
        self.load_config()
    
    def init_ui(self):
        """初始化界面"""
        layout = QVBoxLayout(self)
        
        # 基本设置组
        basic_group = QGroupBox("基本设置")
        basic_layout = QFormLayout(basic_group)
        
        self.auto_backup_checkbox = QCheckBox("启用自动备份")
        basic_layout.addRow("自动备份:", self.auto_backup_checkbox)
        
        self.backup_interval_spinbox = QSpinBox()
        self.backup_interval_spinbox.setRange(1, 168)  # 1小时到1周
        self.backup_interval_spinbox.setSuffix(" 小时")
        basic_layout.addRow("备份间隔:", self.backup_interval_spinbox)
        
        self.close_backup_checkbox = QCheckBox("程序关闭时自动备份")
        basic_layout.addRow("关闭备份:", self.close_backup_checkbox)
        
        self.emergency_backup_checkbox = QCheckBox("异常退出时自动备份")
        basic_layout.addRow("异常退出备份:", self.emergency_backup_checkbox)
        
        layout.addWidget(basic_group)
        
        # 加密设置组
        encryption_group = QGroupBox("加密设置")
        encryption_layout = QFormLayout(encryption_group)
        
        self.encryption_combo = QComboBox()
        self.encryption_combo.addItems(["None", "AES"])
        encryption_layout.addRow("加密类型:", self.encryption_combo)
        
        layout.addWidget(encryption_group)
        
        # 备份内容组
        content_group = QGroupBox("备份内容")
        content_layout = QFormLayout(content_group)
        
        self.backup_database_checkbox = QCheckBox("备份数据库")
        content_layout.addRow("数据库:", self.backup_database_checkbox)
        
        self.backup_config_checkbox = QCheckBox("备份配置文件")
        content_layout.addRow("配置文件:", self.backup_config_checkbox)
        
        self.backup_logs_checkbox = QCheckBox("备份日志文件")
        content_layout.addRow("日志文件:", self.backup_logs_checkbox)
        
        layout.addWidget(content_group)
        
        # 存储设置组
        storage_group = QGroupBox("存储设置")
        storage_layout = QFormLayout(storage_group)
        
        self.backup_path_edit = QLineEdit()
        self.backup_path_button = QPushButton("选择路径")
        self.backup_path_button.clicked.connect(self.select_backup_path)
        
        path_layout = QHBoxLayout()
        path_layout.addWidget(self.backup_path_edit)
        path_layout.addWidget(self.backup_path_button)
        storage_layout.addRow("备份路径:", path_layout)
        
        self.max_files_spinbox = QSpinBox()
        self.max_files_spinbox.setRange(1, 1000)
        self.max_files_spinbox.setSuffix(" 个文件")
        storage_layout.addRow("最大文件数:", self.max_files_spinbox)
        
        layout.addWidget(storage_group)
        
        # 操作按钮
        button_layout = QHBoxLayout()
        
        self.save_button = QPushButton("保存配置")
        self.save_button.clicked.connect(self.save_config)
        button_layout.addWidget(self.save_button)
        
        self.reset_button = QPushButton("重置默认")
        self.reset_button.clicked.connect(self.reset_config)
        button_layout.addWidget(self.reset_button)
        
        layout.addLayout(button_layout)
        
        # 添加弹性空间
        layout.addStretch()
    
    def select_backup_path(self):
        """选择备份路径"""
        path = QFileDialog.getExistingDirectory(self, "选择备份路径")
        if path:
            self.backup_path_edit.setText(path)
    
    def load_config(self):
        """加载配置"""
        try:
            config = self.backup_manager.backup_config
            
            self.auto_backup_checkbox.setChecked(config.get("auto_backup", True))
            self.backup_interval_spinbox.setValue(config.get("auto_backup_interval", 24))
            self.close_backup_checkbox.setChecked(config.get("close_backup", True))
            self.emergency_backup_checkbox.setChecked(config.get("emergency_backup", True))
            
            encryption_type = config.get("encryption_type", "AES")
            index = self.encryption_combo.findText(encryption_type)
            if index >= 0:
                self.encryption_combo.setCurrentIndex(index)
            
            self.backup_database_checkbox.setChecked(config.get("backup_database", True))
            self.backup_config_checkbox.setChecked(config.get("backup_config", True))
            self.backup_logs_checkbox.setChecked(config.get("backup_logs", True))
            
            self.backup_path_edit.setText(config.get("backup_path", ""))
            self.max_files_spinbox.setValue(config.get("max_backup_files", 30))
            
        except Exception as e:
            logger.error(f"加载备份配置失败: {e}")
            QMessageBox.warning(self, "警告", f"加载配置失败: {str(e)}")
    
    def save_config(self):
        """保存配置"""
        try:
            # 记录配置保存开始日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份配置保存开始",
                    "开始保存备份配置",
                    details={
                        "auto_backup": self.auto_backup_checkbox.isChecked(),
                        "backup_interval": self.backup_interval_spinbox.value(),
                        "close_backup": self.close_backup_checkbox.isChecked(),
                        "emergency_backup": self.emergency_backup_checkbox.isChecked(),
                        "encryption_type": self.encryption_combo.currentText(),
                        "backup_database": self.backup_database_checkbox.isChecked(),
                        "backup_config": self.backup_config_checkbox.isChecked(),
                        "backup_logs": self.backup_logs_checkbox.isChecked(),
                        "backup_path": self.backup_path_edit.text(),
                        "max_files": self.max_files_spinbox.value()
                    }
                )
            
            config = {
                "auto_backup": self.auto_backup_checkbox.isChecked(),
                "auto_backup_interval": self.backup_interval_spinbox.value(),
                "close_backup": self.close_backup_checkbox.isChecked(),
                "emergency_backup": self.emergency_backup_checkbox.isChecked(),
                "encryption_type": self.encryption_combo.currentText(),
                "backup_database": self.backup_database_checkbox.isChecked(),
                "backup_config": self.backup_config_checkbox.isChecked(),
                "backup_logs": self.backup_logs_checkbox.isChecked(),
                "backup_path": self.backup_path_edit.text(),
                "max_backup_files": self.max_files_spinbox.value()
            }
            
            self.backup_manager.update_backup_config(**config)
            
            # 记录配置保存成功日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份配置保存完成",
                    "备份配置保存成功",
                    details={"config": config}
                )
            
            QMessageBox.information(self, "成功", "配置已保存")
            
        except Exception as e:
            logger.error(f"保存配置失败: {e}")
            
            # 记录配置保存失败日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "备份配置保存失败",
                    f"保存备份配置失败: {str(e)}",
                    log_level=LogLevel.ERROR,
                    details={"error": str(e), "error_type": type(e).__name__}
                )
            
            QMessageBox.critical(self, "错误", f"保存配置失败: {str(e)}")
    
    def reset_config(self):
        """重置为默认配置"""
        reply = QMessageBox.question(
            self, "确认重置", 
            "确定要重置为默认配置吗？",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            self.load_config()

class BackupListWidget(QWidget):
    """备份文件列表组件"""
    
    def __init__(self, backup_manager, parent=None):
        super().__init__(parent)
        self.backup_manager = backup_manager
        
        # 系统日志管理器
        self.system_logger = get_system_logger() if get_system_logger else None
        
        self.init_ui()
        self.load_backup_list()
    
    def init_ui(self):
        """初始化界面"""
        layout = QVBoxLayout(self)
        
        # 标题
        title_label = QLabel("备份文件列表")
        title_label.setFont(QFont("Arial", 12, QFont.Weight.Bold))
        layout.addWidget(title_label)
        
        # 操作按钮
        button_layout = QHBoxLayout()
        
        self.refresh_button = QPushButton("刷新列表")
        self.refresh_button.clicked.connect(self.load_backup_list)
        button_layout.addWidget(self.refresh_button)
        
        self.create_backup_button = QPushButton("创建备份")
        self.create_backup_button.clicked.connect(self.create_backup)
        button_layout.addWidget(self.create_backup_button)
        
        self.restore_button = QPushButton("恢复备份")
        self.restore_button.clicked.connect(self.restore_backup)
        button_layout.addWidget(self.restore_button)
        
        self.delete_button = QPushButton("删除备份")
        self.delete_button.clicked.connect(self.delete_backup)
        button_layout.addWidget(self.delete_button)
        
        layout.addLayout(button_layout)
        
        # 备份文件表格
        self.backup_table = QTableWidget()
        self.backup_table.setColumnCount(6)
        self.backup_table.setHorizontalHeaderLabels([
            "文件名", "大小", "创建时间", "加密", "状态", "操作"
        ])
        
        # 设置表格属性
        header = self.backup_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
        header.setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(4, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(5, QHeaderView.ResizeMode.ResizeToContents)
        
        self.backup_table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        self.backup_table.setAlternatingRowColors(True)
        
        layout.addWidget(self.backup_table)
        
        # 状态栏
        self.status_label = QLabel("就绪")
        layout.addWidget(self.status_label)
    
    def load_backup_list(self):
        """加载备份文件列表"""
        try:
            self.status_label.setText("正在加载备份列表...")
            
            backup_list = self.backup_manager.get_backup_list()
            
            self.backup_table.setRowCount(len(backup_list))
            
            for row, backup in enumerate(backup_list):
                # 文件名
                name_item = QTableWidgetItem(backup.get("name", ""))
                name_item.setData(Qt.ItemDataRole.UserRole, backup.get("path", ""))
                self.backup_table.setItem(row, 0, name_item)
                
                # 文件大小
                size = backup.get("size", 0)
                size_text = self.format_file_size(size)
                size_item = QTableWidgetItem(size_text)
                self.backup_table.setItem(row, 1, size_item)
                
                # 创建时间
                time_text = backup.get("modified_time", "")
                if time_text:
                    try:
                        dt = datetime.fromisoformat(time_text)
                        time_text = dt.strftime("%Y-%m-%d %H:%M:%S")
                    except:
                        pass
                time_item = QTableWidgetItem(time_text)
                self.backup_table.setItem(row, 2, time_item)
                
                # 加密状态
                encrypted = backup.get("encrypted", False)
                encrypt_item = QTableWidgetItem("是" if encrypted else "否")
                self.backup_table.setItem(row, 3, encrypt_item)
                
                # 状态
                status_item = QTableWidgetItem("正常")
                self.backup_table.setItem(row, 4, status_item)
                
                # 操作按钮
                action_widget = QWidget()
                action_layout = QHBoxLayout(action_widget)
                action_layout.setContentsMargins(2, 2, 2, 2)
                
                restore_btn = QPushButton("恢复")
                restore_btn.setMaximumWidth(60)
                restore_btn.clicked.connect(lambda checked, r=row: self.restore_backup_at_row(r))
                action_layout.addWidget(restore_btn)
                
                delete_btn = QPushButton("删除")
                delete_btn.setMaximumWidth(60)
                delete_btn.clicked.connect(lambda checked, r=row: self.delete_backup_at_row(r))
                action_layout.addWidget(delete_btn)
                
                self.backup_table.setCellWidget(row, 5, action_widget)
            
            self.status_label.setText(f"共找到 {len(backup_list)} 个备份文件")
            
        except Exception as e:
            logger.error(f"加载备份列表失败: {e}")
            self.status_label.setText(f"加载失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"加载备份列表失败: {str(e)}")
    
    def format_file_size(self, size_bytes):
        """格式化文件大小"""
        if size_bytes < 1024:
            return f"{size_bytes} B"
        elif size_bytes < 1024 * 1024:
            return f"{size_bytes / 1024:.1f} KB"
        elif size_bytes < 1024 * 1024 * 1024:
            return f"{size_bytes / (1024 * 1024):.1f} MB"
        else:
            return f"{size_bytes / (1024 * 1024 * 1024):.1f} GB"
    
    def create_backup(self):
        """创建备份"""
        try:
            # 记录创建备份开始日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "手动备份开始",
                    "用户手动创建备份",
                    details={
                        "backup_manager_path": str(self.backup_manager.backup_path),
                        "include_logs": True
                    }
                )
            
            self.status_label.setText("正在创建备份...")
            
            # 创建备份
            backup_path = self.backup_manager.create_backup(include_logs=True)
            
            if backup_path:
                # 记录创建备份成功日志
                if self.system_logger:
                    backup_size = os.path.getsize(backup_path) if os.path.exists(backup_path) else 0
                    self.system_logger.log_system_event(
                        "手动备份完成",
                        f"手动备份创建成功: {os.path.basename(backup_path)}",
                        details={
                            "backup_path": backup_path,
                            "backup_size": backup_size,
                            "backup_name": os.path.basename(backup_path)
                        }
                    )
                
                QMessageBox.information(self, "成功", f"备份创建成功:\n{backup_path}")
                self.load_backup_list()  # 刷新列表
            else:
                # 记录创建备份失败日志
                if self.system_logger:
                    self.system_logger.log_system_event(
                        "手动备份失败",
                        "手动备份创建失败",
                        log_level=LogLevel.ERROR,
                        details={"error": "备份创建返回None"}
                    )
                
                QMessageBox.critical(self, "错误", "备份创建失败")
            
            self.status_label.setText("就绪")
            
        except Exception as e:
            logger.error(f"创建备份失败: {e}")
            
            # 记录创建备份失败日志
            if self.system_logger:
                self.system_logger.log_system_event(
                    "手动备份失败",
                    f"手动备份创建失败: {str(e)}",
                    log_level=LogLevel.ERROR,
                    details={"error": str(e), "error_type": type(e).__name__}
                )
            
            self.status_label.setText("创建失败")
            QMessageBox.critical(self, "错误", f"创建备份失败: {str(e)}")
    
    def restore_backup(self):
        """恢复备份"""
        current_row = self.backup_table.currentRow()
        if current_row < 0:
            QMessageBox.warning(self, "警告", "请先选择一个备份文件")
            return
        
        self.restore_backup_at_row(current_row)
    
    def restore_backup_at_row(self, row):
        """恢复指定行的备份"""
        try:
            backup_path = self.backup_table.item(row, 0).data(Qt.ItemDataRole.UserRole)
            if not backup_path:
                QMessageBox.warning(self, "警告", "无法获取备份文件路径")
                return
            
            # 记录恢复备份开始日志
            if self.system_logger:
                backup_name = os.path.basename(backup_path) if backup_path else "未知"
                self.system_logger.log_system_event(
                    "备份恢复开始",
                    f"用户开始恢复备份: {backup_name}",
                    details={
                        "backup_path": backup_path,
                        "backup_name": backup_name
                    }
                )
            
            reply = QMessageBox.question(
                self, "确认恢复", 
                f"确定要恢复这个备份吗？\n{backup_path}\n\n这将覆盖当前的数据。",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                self.status_label.setText("正在恢复备份...")
                
                success = self.backup_manager.restore_backup(backup_path)
                
                if success:
                    # 记录恢复备份成功日志
                    if self.system_logger:
                        backup_name = os.path.basename(backup_path) if backup_path else "未知"
                        self.system_logger.log_system_event(
                            "备份恢复完成",
                            f"备份恢复成功: {backup_name}",
                            details={
                                "backup_path": backup_path,
                                "backup_name": backup_name,
                                "restore_result": "success"
                            }
                        )
                    
                    QMessageBox.information(self, "成功", "备份恢复成功，需要重启应用程序")
                    # 这里可以发送重启信号
                else:
                    # 记录恢复备份失败日志
                    if self.system_logger:
                        backup_name = os.path.basename(backup_path) if backup_path else "未知"
                        self.system_logger.log_system_event(
                            "备份恢复失败",
                            f"备份恢复失败: {backup_name}",
                            log_level=LogLevel.ERROR,
                            details={
                                "backup_path": backup_path,
                                "backup_name": backup_name,
                                "restore_result": "failed"
                            }
                        )
                    
                    QMessageBox.critical(self, "错误", "备份恢复失败")
                
                self.status_label.setText("就绪")
                
        except Exception as e:
            logger.error(f"恢复备份失败: {e}")
            
            # 记录恢复备份失败日志
            if self.system_logger:
                backup_path = self.backup_table.item(row, 0).data(Qt.ItemDataRole.UserRole) if row >= 0 else "未知"
                backup_name = os.path.basename(backup_path) if backup_path else "未知"
                self.system_logger.log_system_event(
                    "备份恢复失败",
                    f"恢复备份异常: {backup_name}",
                    log_level=LogLevel.ERROR,
                    details={
                        "backup_path": backup_path,
                        "backup_name": backup_name,
                        "error": str(e),
                        "error_type": type(e).__name__
                    }
                )
            
            self.status_label.setText("恢复失败")
            QMessageBox.critical(self, "错误", f"恢复备份失败: {str(e)}")
    
    def delete_backup(self):
        """删除备份"""
        current_row = self.backup_table.currentRow()
        if current_row < 0:
            QMessageBox.warning(self, "警告", "请先选择一个备份文件")
            return
        
        self.delete_backup_at_row(current_row)
    
    def delete_backup_at_row(self, row):
        """删除指定行的备份"""
        try:
            backup_path = self.backup_table.item(row, 0).data(Qt.ItemDataRole.UserRole)
            if not backup_path:
                QMessageBox.warning(self, "警告", "无法获取备份文件路径")
                return
            
            # 记录删除备份开始日志
            if self.system_logger:
                backup_name = os.path.basename(backup_path) if backup_path else "未知"
                file_size = os.path.getsize(backup_path) if os.path.exists(backup_path) else 0
                self.system_logger.log_system_event(
                    "备份删除开始",
                    f"用户开始删除备份: {backup_name}",
                    details={
                        "backup_path": backup_path,
                        "backup_name": backup_name,
                        "file_size": file_size
                    }
                )
            
            reply = QMessageBox.question(
                self, "确认删除", 
                f"确定要删除这个备份文件吗？\n{backup_path}",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                self.status_label.setText("正在删除备份...")
                
                # 使用备份管理器的删除方法
                success = self.backup_manager.delete_backup(backup_path)
                
                if success:
                    # 记录删除备份成功日志
                    if self.system_logger:
                        backup_name = os.path.basename(backup_path) if backup_path else "未知"
                        self.system_logger.log_system_event(
                            "备份删除完成",
                            f"备份删除成功: {backup_name}",
                            details={
                                "backup_path": backup_path,
                                "backup_name": backup_name,
                                "delete_result": "success"
                            }
                        )
                    
                    QMessageBox.information(self, "成功", "备份文件删除成功")
                    self.load_backup_list()  # 刷新列表
                else:
                    # 记录删除备份失败日志
                    if self.system_logger:
                        backup_name = os.path.basename(backup_path) if backup_path else "未知"
                        self.system_logger.log_system_event(
                            "备份删除失败",
                            f"备份删除失败: {backup_name}",
                            log_level=LogLevel.ERROR,
                            details={
                                "backup_path": backup_path,
                                "backup_name": backup_name,
                                "delete_result": "failed"
                            }
                        )
                    
                    QMessageBox.warning(self, "警告", "备份文件删除失败")
                
                self.status_label.setText("就绪")
                
        except Exception as e:
            logger.error(f"删除备份失败: {e}")
            
            # 记录删除备份失败日志
            if self.system_logger:
                backup_path = self.backup_table.item(row, 0).data(Qt.ItemDataRole.UserRole) if row >= 0 else "未知"
                backup_name = os.path.basename(backup_path) if backup_path else "未知"
                self.system_logger.log_system_event(
                    "备份删除失败",
                    f"删除备份异常: {backup_name}",
                    log_level=LogLevel.ERROR,
                    details={
                        "backup_path": backup_path,
                        "backup_name": backup_name,
                        "error": str(e),
                        "error_type": type(e).__name__
                    }
                )
            
            self.status_label.setText("删除失败")
            QMessageBox.critical(self, "错误", f"删除备份失败: {str(e)}")

class BackupDialog(QDialog):
    """备份设置对话框"""
    
    def __init__(self, backup_manager, parent=None):
        super().__init__(parent)
        self.backup_manager = backup_manager
        self.init_ui()
    
    def init_ui(self):
        """初始化界面"""
        self.setWindowTitle("备份设置")
        self.setMinimumSize(800, 600)
        
        layout = QVBoxLayout(self)
        
        # 创建标签页
        tab_widget = QTabWidget()
        
        # 配置标签页
        config_widget = BackupConfigWidget(self.backup_manager)
        tab_widget.addTab(config_widget, "备份配置")
        
        # 备份列表标签页
        list_widget = BackupListWidget(self.backup_manager)
        tab_widget.addTab(list_widget, "备份文件")
        
        layout.addWidget(tab_widget)
        
        # 关闭按钮
        close_button = QPushButton("关闭")
        close_button.clicked.connect(self.close)
        layout.addWidget(close_button) 